package ar.com.coonocer.joy.mdg.util.templating.gsp;

import groovy.lang.GroovyShell;
import groovy.lang.Writable;
import groovy.text.SimpleTemplateEngine;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.CompilerConfiguration;

import ar.com.coonocer.joy.mdg.util.SettingsHolder;
import ar.com.coonocer.joy.mdg.xmi.core.ModelElement;
import ar.com.coonocer.joy.mdg.xmi.model.Model;

public class GSPTemplateUtil {

	public static final String TEMPLATE_EXTENSION = ".gsp";

	public static void applyTemplate(Model model, ModelElement umlObject, File templateFolder, File templateFile, File destinationFileIn) {
		//
		Context ctx = new Context(SettingsHolder.getSettings(), destinationFileIn);
		//
		Writable writable = executeGSPTemplate(model, umlObject, templateFolder, templateFile, null, ctx);
		//
		if (!ctx.isSkipFile()) {
			//
			if (ctx.getBinaryData() == null) {
				FileUtil.saveResponseToFile(writable, ctx.getDestinationFile());
			} else {
				FileUtil.saveResponseToFile(ctx.getBinaryData(), ctx.getDestinationFile());
			}
		}
	}

	//Se informa template file o template text, uno de los dos
	public static Writable executeGSPTemplate(Model model, Object umlObject, File templateFolder, File templateFile, String templateText, Context ctx) {
		CompilerConfiguration compilerConfiguration = new CompilerConfiguration();
		List<String> classpathList = new ArrayList<String>();
		classpathList.add(templateFolder.getAbsolutePath() + "/scripts");
		//
		//TODO: detectar jars en carpeta de libs y agregarlos.
		//classpathList.add(templateFolder.getAbsolutePath() + "/libs/ojdbc6.jar");
		//
		compilerConfiguration.setClasspathList(classpathList);
		//
		GroovyShell groovyShell = new GroovyShell(compilerConfiguration);
		SimpleTemplateEngine engine = new SimpleTemplateEngine(groovyShell);
		//
		engine.setVerbose(false);
		//
		groovy.text.Template template;
		try {
			if (templateFile != null) {
				template = engine.createTemplate(templateFile);
			} else {
				template = engine.createTemplate(templateText);
			}
		} catch (CompilationFailedException e) {
			throw new RuntimeException("Error evaluating template file: " + templateFile, e);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("Error evaluating template file: " + templateFile, e);
		} catch (IOException e) {
			throw new RuntimeException("Error evaluating template file: " + templateFile, e);
		}
		//
		Map<String, Object> data = instantiateContext(model, templateFolder, umlObject, ctx);
		//
		Writable writable = template.make(data);
		//
		return writable;
	}

	public static Map<String, Object> instantiateContext(Model model, File templateFolder, Object umlObject, Context ctx) {
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("model", model);
		data.put("object", umlObject);
		data.put("ctx", ctx);
		return data;
	}
}
